<template>
    <div>
        <!-- 实名认证组件的结构 -->
        <el-card class="box-card">
            <!-- 卡片的头部 -->
            <template #header>
                <div class="card-header">
                    <h1>实名信息</h1>
                </div>
            </template>
            <!-- 实名认证结构的提示部分 -->
            <div class="tip" style="color: #7f7f7f;">
                <p>
                    <el-icon>
                        <InfoFilled />
                    </el-icon>
                    完成实名认证后才能添加就诊人，正常进行挂号，为了不影响后续步骤，建议提前实名认证。
                </p>
            </div>
            <!-- 卡片身体的底部：认证成功的结构，认证未成功的结构 -->
            <!-- 左侧展示订单详情信息 -->
            <el-descriptions v-if="userInfo.authStatus == 1" class="margin-top" :column="1" border
                style="margin: 20px auto;">
                <el-descriptions-item label-align="center" width="50px">
                    <template #label>
                        <div class="cell-item">用户姓名</div>
                    </template>
                    {{ userInfo.name }}
                </el-descriptions-item>
                <el-descriptions-item label-align="center" width="50px">
                    <template #label>
                        <div class="cell-item">证件类型</div>
                    </template>
                    {{ userInfo.certificatesType == '10' ? '身份证' : '户口本' }}
                </el-descriptions-item>
                <el-descriptions-item label-align="center" width="50px">
                    <template #label>
                        <div class="cell-item">证件号码</div>
                    </template>
                    {{ userInfo.certificatesNo }}
                </el-descriptions-item>
            </el-descriptions>
            <!-- 用户未验证的结构 -->
            <el-form v-if="userInfo.authStatus == 0" 
                style="width: 60%;margin: 20px auto;" 
                label-width="80" 
                :model="params"
                :rules="rules"
                ref="form">
                <el-form-item label="用户姓名" prop="name">
                    <el-input placeholder="请输入用户姓名" v-model="params.name"></el-input>
                </el-form-item>
                <el-form-item label="证件类型" prop="certificatesType">
                    <el-select style="width: 100%;" placeholder="请选择证件类型" v-model="params.certificatesType">
                        <el-option :label="item.name" :value="item.value" v-for="(item, index) in arrType"
                            :key="index"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="证件号码" prop="certificatesNo">
                    <el-input placeholder="请输入证件号码" v-model="params.certificatesNo"></el-input>
                </el-form-item>
                <el-form-item label="上传证件" prop="certificatesUrl">
                    <!-- 
                        action: upload 组件向服务器提交图片的路径 
                        limit: 照片墙允许上传文件的最大数量
                        on-exceed: 超出约束数量的钩子
                    -->
                    <el-upload ref="upload" list-type="picture-card" :on-preview="handlePictureCardPreView"
                        :on-remove="handleRemove" action="/api/oss/file/fileUpload?fileHost=userAuah" limit="1"
                        :on-exceed="exceedHandler" :on-success="successHandler">
                        <img style="width: 100%;height: 100%;" src="../../../assets/images/auth_example.png" alt="" />
                    </el-upload>

                    <el-dialog v-model="dialogVisible">
                        <img w-full v-if="params.certificatesUrl" style="width: 100%;height: 100%;"
                            :src="params.certificatesUrl" alt="Priview Image" />
                    </el-dialog>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" size="default" @click="submit">提交</el-button>
                    <el-button type="primary" size="default" @click="reset">重写</el-button>
                </el-form-item>
            </el-form>
        </el-card>
    </div>
</template>

<script setup lang="ts">
//引入 elment-plus 图标
import { InfoFilled } from '@element-plus/icons-vue';

//获取用户信息
import { reqUserInfo, reqCertationType, reqUserCertation } from '@/api/user';
import type {
    UserInfoResponseData,
    CertificatesTypeResponseData,
    CertificatesArr,
    UserParams
} from '@/api/user/type';
//引入组合式 API 函数
import { onMounted, ref, reactive } from 'vue';
import { ElMessage } from 'element-plus';
//获取 form 组件
let form = ref();
//存储用户信息
let userInfo: any = ref<any>({});
let arrType = ref<CertificatesArr>([]);
//控制对话框的显示与隐藏
let dialogVisible = ref<boolean>(false);
//收集用户表单认证的数据
let params = reactive<UserParams>({
    "certificatesNo": '',
    "certificatesType": '',
    "certificatesUrl": '',
    "name": ''
});
let upload = ref();

//组件挂载完毕
onMounted(() => {
    ////获取用户信息
    getUserInfo();
    //获取证件类型的接口
    getType();
});

//获取用户信息的方法
const getUserInfo = async () => {
    let result: UserInfoResponseData = await reqUserInfo();
    if (result.code == 200) {
        userInfo.value = result.data;
    }
};

//获取证件类型的接口
const getType = async () => {
    let result: CertificatesTypeResponseData = await reqCertationType();
    if (result.code == 200) {
        arrType.value = result.data;
    }
}

//超出数量的钩子
const exceedHandler = () => {
    ElMessage({
        type: 'error',
        message: '图片只能上传一张'
    });
}

//@ts-ignore
//图片上传成功的钩子
const successHandler = (response: any) => {
    //如果图片上传成功，清除校验的结果
    form.value.clearValidate('certificatesUrl');

    //收集上传成功的图片的地址
    //response: 上传图片成功服务器返回的数据
    //uploadFile: 上传文件对象
    //uploadFiles: 上传图片所有对象的集合
    params.certificatesUrl = response.data;
}

//照片墙预览的钩子
const handlePictureCardPreView = () => {
    //触发预览钩子的时候，对话框显示
    dialogVisible.value = true;
}

//照片墙删除的钩子
const handleRemove = () => {
    params.certificatesUrl = '';
}

//重写按钮的回调
const reset = () => {
    //清空上传组件文件列表
    upload.value.clearFiles();
    //清空数据
    Object.assign(params, {
        "certificatesNo": '',
        "certificatesType": '',
        "certificatesUrl": '',
        "name": ''
    });
};
//提交按钮的回调
const submit = async () => {
    //全部的表单校验通过，返回一个成功的 Promise
    //如果有一个表单校验失败，返回一个失败的 Promise，后面的语句不再执行
    await form.value.validate();

    try {
        //认证成功
        await reqUserCertation(params);
        //提示消息
        ElMessage({
            type: 'success',
            message: '认证成功'
        });
        //认证成功之后重新获取用户信息
        getUserInfo();
    } catch (error) {
        ElMessage({
            type: 'error',
            message: '认证失败'
        });
    }
};

//自定义校验规则姓名的方法
//rule: 当前校验字段的规则对象
//value: 要校验表单元素的文本内容
//callBack: 是否通过校验
//@ts-ignore
const validatorName = (rule: any, value: any, callBack: any) => {
    var reg = /^[\u00B7\u3007\u3400-\u4DBF\u4E00-\u9FFF\uE000-\uF8FF\uD840-\uD8C0\uDC00-\uDFFF\uF900-\uFAFF]+$/;
    if (reg.test(value)) {
        callBack();
    } else {
        callBack(new Error('请输入正确的中国人的名字'));
    }
};

//证件类型校验的方法
//@ts-ignore
const validatorType = (rule: any, value: any, callBack: any) => {
    if (value == '10' || value == '20') {
        callBack();
    } else {
        callBack(new Error('请选择证件类型'));
    }
};

//证件号码校验的方法
//@ts-ignore
const validatorNo = (rule: any, value: any, callBack: any) => {
    var sfz = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;  
    let hkb = /^\d{9}$/;
    if (sfz.test(value) || hkb.test(value)) {
        callBack();
    } else {
        callBack(new Error('请输入正确的证件号码'));
    }
};

//证件照图片校验的方法
//@ts-ignore
const validatorUrl = (rule: any, value: any, callBack: any) => {
    if (value.length) {
        callBack();
    } else {
        callBack(new Error('请上传证件照图片'));
    }
};

//表单校验的规则对象
const rules = {
    //用户姓名的校验规则
    //required=true:代表当前字段必须校验
    name: [{
        required: true,
        validator: validatorName
    }],
    certificatesType: [{
        required: true,
        validator: validatorType
    }],
    certificatesNo: [{
        required: true,
        validator: validatorNo
    }],
    certificatesUrl: [{
        required: true,
        validator: validatorUrl
    }]
};
</script>

<style scoped lang="scss">
.box-card {
    .tip {
        display: flex;
        justify-content: center;
        align-items: center;
    }
}
</style>